package com.gitee.wsl.ext.math

import kotlin.math.min

object PositionExt {
    /**
     * key up key event, cycle move
     *
     * @param parent
     * @param numColumns
     * @param handleKey 是否手动处理
     * @return
     */

    fun moveUp(selectPos:Int, count:Int, numColumns: Int=count,handleKey:Boolean=false): Int  {
        var selectedPosition = selectPos
        val lastPos = count - 1

        /**
         * 取最大 <= firstLine 是第一行
         */
        val firstLine = numColumns - 1

        /**
         * 取最小 >= lastLine 是最后一行
         */
        val lastLine = lastPos - lastPos % numColumns
        if (selectedPosition <= firstLine) {
            selectedPosition = min(lastLine + selectedPosition, lastPos)
        }
        if (handleKey) {
            /**
             * 手动设置：带锁弹框上下移动消失，并且需要传递key事件给列表时，需要手动设置选中，这样会选中下一个
             * 否则return false，自动选中，是不会选中下一个
             */
            selectedPosition -= numColumns
            selectedPosition = if (selectedPosition < 0) lastPos else selectedPosition

        }
        return selectedPosition
    }


    /**
     * key down key event, cycle move
     *
     * @param parent
     * @param numColumns
     * @param handleKey 是否手动处理
     * @return
     */
    fun moveDown(selectPos:Int, count:Int, numColumns: Int=count,handleKey:Boolean=false): Int  {
        var selectedPosition = selectPos
        val lastPos = count - 1
        val lastLine = lastPos - lastPos % numColumns
        if (selectedPosition >= lastLine) {
            selectedPosition = min(selectedPosition % numColumns, lastPos)

        } else if (selectedPosition + numColumns > lastPos) {
            selectedPosition = lastPos
        }
        if (handleKey) {
            /**
             * 手动设置
             */
            selectedPosition += numColumns
            selectedPosition = if (selectedPosition > lastPos) 0 else selectedPosition
        }
        return selectedPosition
    }

    /**
     * key down key event, cycle move
     *
     * @param parent
     * @param numColumns
     * @return
     */
    fun moveLeft(selectPos:Int, count:Int, numColumns: Int=count): Int  {
        if (numColumns <= 1) {
            return -1
        }
        var selectedPosition = selectPos
        val lastPos = count - 1
        selectedPosition -= 1
        if (selectedPosition < 0) {
            selectedPosition = lastPos

        } else if ((selectedPosition + 1) % numColumns == 0) {

        }
        return selectedPosition
    }

    /**
     * key down key event, cycle move
     *
     * @param parent
     * @param numColumns
     * @return
     */

    fun moveRight(selectPos:Int, count:Int, numColumns: Int=count): Int {
        if (numColumns <= 1) {
            return -1
        }
        var selectedPosition = selectPos
        val lastPos = count - 1
        selectedPosition += 1
        if (selectedPosition > lastPos) {
            selectedPosition = 0

        }
        return selectedPosition
    }

    /**
     * page up key event, cycle move
     *
     * @param parent
     * @param pageItemCount
     */

    fun movePageUp(selectPos:Int,count:Int, pageItemCount: Int = count): Int {
        val selectPos1 = if (selectPos == 0) {
            count - 1
        } else {
            if (selectPos - pageItemCount < 0) {
                0
            } else {
                selectPos - pageItemCount
            }
        }
        return selectPos1
    }

    /**
     * page down key event, cycle move
     *
     * @param parent
     * @param pageItemCount
     */
    fun movePageDown(selectPos1:Int,count:Int, pageItemCount: Int = count): Int {
        val selectPos = if (selectPos1 == count - 1) {
            0
        } else {
            if (selectPos1 + pageItemCount >= count) {
                count - 1
            } else {
                selectPos1 + pageItemCount
            }
        }
        return selectPos
    }

}

interface PositionAble<T>{
    var selectPosition:Int

    fun moveLeft( block:(newPosition:Int, T)->Unit)

    fun moveRight( block:(newPosition:Int, T)->Unit)
}

inline  fun <T> List<T>.moveLeft(selectPos:Int, crossinline block:(newPosition:Int, T)->Unit){
    val newPosition = PositionExt.moveLeft(selectPos,count())
    if(newPosition!=-1 && newPosition != selectPos){
        block(newPosition,get(newPosition))
    }
}

inline  fun <T> List<T>.moveRight(selectPos:Int, crossinline block:(newPosition:Int, T)->Unit){
    val newPosition = PositionExt.moveRight(selectPos,count())
    if(newPosition !=-1 && newPosition != selectPos){
        block(newPosition,get(newPosition))
    }
}

fun <T> List<T>.positionAble():PositionAble<T>{
    return object :PositionAble<T>{
        override var selectPosition: Int = -1

        override fun moveRight(block: (newPosition: Int, T) -> Unit) {
            moveRight(selectPosition) { newPosition, t ->
                selectPosition=newPosition
                block(newPosition,t)
            }
        }

        override fun moveLeft(block: (newPosition: Int, T) -> Unit) {
            moveLeft(selectPosition){newPosition, t ->
                selectPosition=newPosition
                block(newPosition,t)
            }
        }

    }
}

interface WindowAble<T>:PositionAble<T>{
    var startPosition:Int
    var endPosition:Int

    fun moveWindow(step:Int)
}

fun <T> List<T>.windowAble(startPosition1:Int,endPosition1:Int):WindowAble<T>{
    val baseList=this
    return object :WindowAble<T>{

        var currentList:List<T> = emptyList()

        override var startPosition: Int =0

        override var endPosition: Int =0

        init {
            initList(startPosition1,endPosition1)
        }

        private fun initList(startPosition1:Int,endPosition1:Int){
            selectPosition = -1

            endPosition = min(endPosition1,baseList.size-1)

            startPosition = min( startPosition1,endPosition)

            currentList = baseList.subList(startPosition,endPosition)
        }

        override fun moveWindow(step: Int) {
            initList(startPosition+step,endPosition+step)
        }

        override var selectPosition: Int = -1

        override fun moveRight(block: (newPosition: Int, T) -> Unit) {
            currentList.moveRight(selectPosition) { newPosition, t ->
                selectPosition=newPosition
                block(newPosition,t)
            }
        }

        override fun moveLeft(block: (newPosition: Int, T) -> Unit) {
            currentList.moveLeft(selectPosition){newPosition, t ->
                selectPosition=newPosition
                block(newPosition,t)
            }
        }

    }
}